home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 003 / _gs / !GS / c / gsmain < prev    next >
Text File  |  1991-10-27  |  7KB  |  239 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gsmain.c */
  21. /* Framework for GhostScript drivers */
  22. #include "string_.h"
  23. #include "memory_.h"
  24. #include "gx.h"
  25. #include "gp.h"
  26. #include "gsmatrix.h"            /* for gxdevice.h */
  27. #include "gxdevice.h"
  28. #include "gxdevmem.h"
  29.  
  30. /*
  31.  * This routine provides the following standard services for parsing
  32.  * a command line:
  33.  *    - setting debug flags (-Z switch) [if debugging];
  34.  *    - tracing (-T switch);
  35.  *    - passing other arguments and switches back to the caller
  36.  *
  37.  * Calling convention:
  38.  *    gs_main(argc, argv, map_name, switch_proc, arg_proc)
  39.  * Calls
  40.  *    switch_proc(&switch, rest_of_arg) for switches,
  41.  *    arg_proc(&arg, index) for non-switch args.
  42.  * If switch_proc returns a negative value, gs_main prints an
  43.  *   "unknown switch" error message and aborts.
  44.  * gs_main returns the number of non-switch args handed to arg_proc.
  45.  */
  46.  
  47. /* Imported data */
  48. extern gx_device *gx_device_list[];
  49.  
  50. private long proc_reloc;    /* relocation of procedures */
  51.  
  52. void gs_exit(P1(int));
  53.  
  54. int
  55. gs_main(int argc, char *argv[], char *map_name,
  56.     int (*switch_proc)(P2(char **, char *)),
  57.     void (*arg_proc)(P2(char **, int)))
  58. {    int argi = 1;
  59.     FILE *mapf = NULL;
  60.     int arg_count = 0;
  61.     proc_reloc = 0;
  62.     gs_out = stdout;
  63. #ifdef DEBUG
  64.     gs_debug_out = stdout;
  65.     /* Reset debugging flags */
  66.     memset(gs_debug, 0, 128);
  67. #endif
  68.     /* If debugging is enabled, trace the device calls. */
  69. #ifdef DEBUG
  70.        {    extern gx_device *gs_trace_device(P1(gx_device *));
  71.         extern gx_device_memory
  72.             mem_mono_device, mem_mapped8_color_device,
  73.             mem_true24_color_device, mem_true32_color_device;
  74.         static gx_device_memory *mdevs[5] =
  75.            {    &mem_mono_device, &mem_mapped8_color_device,
  76.             &mem_true24_color_device, &mem_true32_color_device,
  77.             0
  78.            };
  79.         extern gx_device gs_clist_device;    /* gx_clist_device */
  80.         static gx_device *cldevs[2] =
  81.            {    &gs_clist_device,
  82.             0
  83.            };
  84.         gx_device **pdevs[4];
  85.         gx_device ***ppdev;
  86.         gx_device **pdev;
  87.         pdevs[0] = gx_device_list;
  88.         pdevs[1] = (gx_device **)mdevs;
  89.         pdevs[2] = cldevs;
  90.         pdevs[3] = 0;
  91.         for ( ppdev = pdevs; *ppdev != 0; ppdev++ )
  92.          for ( pdev = *ppdev; *pdev != 0; pdev++ )
  93.            {    gx_device *tdev = gs_trace_device(*pdev);
  94.             if ( tdev == 0 )
  95.                {    lprintf("Can't allocate traced device!\n");
  96.                 gs_exit(1);
  97.                }
  98.             *pdev = tdev;
  99.            }
  100.        }
  101. #endif
  102.     for ( ; argi < argc; argi++ )
  103.        {    char **argp = &argv[argi];
  104.         char *arg = *argp;
  105.         if ( *arg == '-' )
  106.            {    switch ( *++arg )
  107.                {
  108.             default:
  109.                 if ( (*switch_proc)(argp, arg + 1) < 0 )
  110.                     printf("Unknown switch %s - ignoring\n", arg - 1);
  111.                 break;
  112.             case 'Z':
  113. #ifdef DEBUG
  114.                 /* Print the address of 'main' so that */
  115.                 /* we can decipher stack traces later. */
  116.                {    extern main();
  117.                 printf("[Z]main = %lx\n", (ulong)main);
  118.                }
  119.                 if ( !arg[1] )
  120.                    {    /* No options, set all flags */
  121.                     memset(gs_debug, -1, 128);
  122.                    }
  123.                 else
  124.                    {    while ( *++arg )
  125.                         gs_debug[*arg & 127] = -1;
  126.                    }
  127. #else
  128.                 printf("Not a debugging configuration, -Z switch ignored\n");
  129. #endif
  130.                 break;
  131.             case 'T':
  132.             if ( mapf == NULL )
  133.                {    /* Open the map file and look up 'main' */
  134.                 extern FILE *trace_open_map(P2(char *, long *));
  135.                 mapf = trace_open_map(map_name, &proc_reloc);
  136.                 if ( mapf == NULL )
  137.                    {    printf("Map file %s is apparently missing or malformed\n", map_name);
  138.                     break;
  139.                    }
  140.                 /* Print the address of 'main' so that */
  141.                 /* we can decipher return addresses later. */
  142.                {    extern main();
  143.                 printf("[T]main = %lx\n", (ulong)main);
  144.                }
  145.                }
  146.                {    char *delim;
  147.                 char *tname;
  148.                 char *targs = NULL;
  149.                 int rsize = 0;
  150.                 extern int trace_flush_flag;
  151.                 delim = strchr(arg, ':');
  152.                 if ( delim != NULL )
  153.                    {    sscanf(delim + 1, "%d", &rsize);
  154.                     *delim = 0;    /* terminate name */
  155.                     delim = strchr(delim + 1, ':');
  156.                     if ( delim != NULL )
  157.                         targs = delim + 1;
  158.                    }
  159.                 tname = gs_malloc(strlen(arg) + 1, 1,
  160.                           "-T switch");
  161.                 strcpy(tname, arg);
  162.                 *tname = '_';
  163.                 strupr(tname);
  164.                 if ( trace_name(tname, mapf, targs, rsize) < 0 )
  165.                     printf("%s not found\n", tname);
  166.                 trace_flush_flag = 1;
  167.                }
  168.                 break;
  169.                }
  170.            }
  171.         else
  172.             (*arg_proc)(argp, arg_count++);
  173.        }
  174.     return arg_count;
  175. }
  176.  
  177. /* Free all resources and exit. */
  178. void gs_malloc_release(P0());
  179. int gs_closedevice(P1(gx_device *));
  180. void
  181. gs_exit(int code)
  182. {    gx_device **pdev = gx_device_list;
  183.     if ( code != 0 ) fflush(stderr);    /* in case of error exit */
  184.     for ( ; *pdev != 0; pdev++ )
  185.       gs_closedevice(*pdev);
  186.     /* Release all memory acquired with malloc. */
  187.     gs_malloc_release();
  188.     exit(code);
  189. }
  190.  
  191. /* ------ Debugging routines ------ */
  192.  
  193. #ifdef DEBUG            /* ------ ------ */
  194.  
  195. void gs_dump_C_stack();
  196.  
  197. /* Log an error return */
  198. int
  199. gs_log_error(int err, char *file, int line)
  200. {    if ( gs_debug['e'] || gs_debug['E'] )
  201.       { if ( file == NULL )
  202.           dprintf1("Returning error %d\n", err);
  203.         else
  204.           dprintf3("%s(%d): returning error %d\n", file, line, err);
  205.         if ( gs_debug['E'] )
  206.           gs_dump_C_stack();
  207.       }
  208.     return err;
  209. }
  210.  
  211. #endif                /* ------ ifdef DEBUG ------ */
  212.  
  213. /* Dump the C stack. */
  214. /* This is actually only used for debugging. */
  215. extern char *stack_top_frame();
  216. extern unsigned long stack_return(P1(char *));
  217. extern char *stack_next_frame(P1(char *));
  218. void
  219. gs_dump_C_stack()
  220. #ifdef ARC
  221. /* I have disabled this stuff - the Acorn debugger is much better, and it
  222.    means I don't need to get into stupid details about the implementation's
  223.    internals
  224. */
  225. { printf("** Stack dump - disabled **\n"); }
  226. #else
  227. {    char *nbp = stack_top_frame();
  228.     char *bp;
  229.     do
  230.        {    bp = nbp;
  231.         dprintf3("frame %8lx called from %8lx (%8lx)\n",
  232.              (unsigned long)bp, stack_return(bp),
  233.              stack_return(bp) - proc_reloc);
  234.         nbp = stack_next_frame(bp);
  235.        }
  236.     while ( nbp != 0 );
  237. }
  238. #endif
  239.